/*
 *
 * Saturn Framework Co.Limt
 * Copyright (c) 2012-2019 tanks, Inc. All rights reserved.
 */

package com.saturn.config.server.web;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.WebUtils;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.saturn.config.server.IConstants;
import com.saturn.config.server.base.R;
import com.saturn.config.server.base.dto.JsonResult;
import com.saturn.config.server.base.entity.AppConfig;
import com.saturn.config.server.base.entity.SysUser;
import com.saturn.config.server.service.AppConfigService;
import com.saturn.config.server.util.YamlPropUtil;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * <dl>
 * <dt><b>Title:</b></dt>
 * <dd>none</dd>
 * <dt><b>Description:</b></dt>
 * <dd>
 * <p>
 * 应用配置项</dd>
 *
 * @author tanks
 * @date 2019-07-08 14:50:16
 */
@Slf4j
@Controller
@AllArgsConstructor
@RequestMapping("/appconfig")
@SuppressWarnings({ "rawtypes", "unchecked" })
public class AppConfigController {

	private final AppConfigService appConfigService;

	/**
	 * 分页查询
	 * 
	 * @param page      分页对象
	 * @param appConfig 应用配置项
	 * @return
	 */
	@RequestMapping(value = "/page", produces = "application/json")
	public @ResponseBody IPage<?> page(HttpServletRequest request,Page page, AppConfig appConfig) {
		Map<String,Object> params = WebUtils.getParametersStartingWith(request,StringUtils.EMPTY);
		String start = request.getParameter("start");
		String limit = request.getParameter("limit");
		if( StringUtils.isNotBlank(start) ) {
			page.setCurrent(Long.parseLong(start)/50 + 1);
		}else {
			page.setCurrent(1l);
		}
		if( StringUtils.isNotBlank(limit) ) {
			page.setSize(Long.parseLong(limit));
		}else {
			page.setSize(20l);
		}
		List<String> keys = new ArrayList<String>();
		for(String key:params.keySet()) {
			String value = (String) params.get(key);
			if( StringUtils.isBlank(value) ) {
				keys.add(key);
			}
		}
		for(String key:keys) {
			params.remove(key);
		}
		return appConfigService.queryPage(page, params);
	}

	/**
	 * 通过id查询应用配置项
	 * 
	 * @param configId id
	 * @return R
	 */
	@GetMapping("/{configId}")
	public R getById(@PathVariable("configId") Long configId) {
		return new R<>(appConfigService.getById(configId));
	}

	/**
	 * 新增应用配置项
	 * 
	 * @param appConfig 应用配置项
	 * @return R
	 */
	@RequestMapping(value = "/save", produces = "application/json")
	public @ResponseBody R save(HttpServletRequest request,AppConfig appConfig) {
		SysUser loginUser = (SysUser)request.getSession().getAttribute("useInfo");
		appConfig.setCreateTime(LocalDateTime.now());
		appConfig.setUserId(loginUser.getId());
		R<?> result = new R();
		boolean op = appConfigService.saveAdd(appConfig);
		result.setCode(op ? IConstants.SUCCESS:IConstants.FAIL);
		result.setMsg(op ? "保存成功！":"保存失败!");
		result.setSuccess(op);
		return result;
	}

	/**
	 * 批量数据删除
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping(value = "/deleteConfigRecords",produces="application/json")
	public @ResponseBody JsonResult deleteRecord(@RequestParam("configIds") String[] configIds) {
		JsonResult response = new JsonResult();
		if( configIds==null || configIds.length==0 ){
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("删除失败！");
		}
		try{
			int size = this.appConfigService.deleteRecords(configIds);
			if( size>0 ){
				response.setSuccess(Boolean.TRUE.booleanValue());
				response.setRespMsg("删除成功,总共" + size + "条记录！");
			}else{
				response.setSuccess(Boolean.FALSE.booleanValue());
				response.setRespMsg("删除失败！");
			}
		}catch(Exception ex){
			log.error("失败",ex);
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("操作失败");
		}
		return response;
	}
	
	/** 
	 * 批量保存数据
	 * @param request
	 * @return
	 * @throws BusinessException
	 */
	@RequestMapping(value = "batchSaveConfigRecord",produces="application/json")
	public @ResponseBody JsonResult batchSaveConfigRecord(HttpServletRequest request) {
		JsonResult response = new JsonResult();
		String jsonText = request.getParameter("datas");
		List<AppConfig> appConfigs = JSONObject.parseArray(jsonText, AppConfig.class);
		try{
			SysUser loginUser = (SysUser)request.getSession().getAttribute("useInfo");
			if( appConfigs!=null && appConfigs.size()>0 ) {
				for(AppConfig appConfig:appConfigs) {
					appConfig.setUserId(loginUser.getId());
				}
			}
			int size = this.appConfigService.batchSaveConfigRecord(appConfigs);
			if( size>0 ){
				response.setSuccess(Boolean.TRUE.booleanValue());
				response.setRespMsg("保存数据成功，更新记录数【" + size + "】条！");
			}else{
				response.setSuccess(Boolean.FALSE.booleanValue());
				response.setRespMsg("保存数据失败！");
			}
		}catch(Exception ex){
			log.error("失败",ex);
			response.setSuccess(Boolean.FALSE.booleanValue());
			response.setRespMsg("保存数据失败");
		}
		return response;
	}

	/**
	 * 批量上传文件
	 * @param request
	 * @param basicId
	 * @param overProp
	 * @param file
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping(value = "/saveUploadConfigFile", method = RequestMethod.POST)
	public void saveUploadConfigFile(HttpServletRequest request, String appId,String overProp,MultipartFile file,HttpServletResponse response) throws IOException {
		JsonResult jsonResult = new JsonResult();
		if (file.getOriginalFilename() != null && !file.getOriginalFilename().equals("") 
				&& (file.getOriginalFilename().indexOf(".yml")>0 || file.getOriginalFilename().indexOf(".properties")>0) ) {
			Properties props = new Properties();
			InputStream input = file.getInputStream();
			try {
				if( file.getOriginalFilename().indexOf(".yml")>0 ) {
					props = YamlPropUtil.yml2Properties(input);
				}else {
					props.load(input);
				}
			}finally {
				try {
					if( input!=null ) input.close();
				}catch(Exception ex) {}
			}
			if( props==null || props.size()==0 ) {
				jsonResult.setSuccess(Boolean.FALSE.booleanValue());
				jsonResult.setRespMsg("文件内容记录为空，上传失败！");
			}else {
				SysUser loginUser = (SysUser)request.getSession().getAttribute("useInfo");
				int effectCount = appConfigService.uploadProperties(loginUser,props, overProp!=null && overProp.equals("on")?true:false, appId);
				jsonResult.setSuccess(Boolean.TRUE.booleanValue());
				jsonResult.setRespMsg("上传配置成功,添加更新[" + effectCount + "]条记录！");
			}
		}else{
			jsonResult.setSuccess(Boolean.TRUE.booleanValue());
			jsonResult.setRespMsg("请上传properties或yaml文件格式！");
		}
		response.setContentType("text/html; charset=UTF-8");
		response.getWriter().write(JSONObject.toJSONString(jsonResult).toString());
	}
	
	/**
	 * 批量模式新增
	 * @param basicId
	 * @param configKeys
	 * @param overProp
	 * @param memo
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "saveBatchAddConfig", method = RequestMethod.POST,produces="application/json")
	public  @ResponseBody R saveBatchAddConfig(HttpServletRequest request,@RequestParam("appId") String appId,@RequestParam("configKeys") String configKeys,String overProp,String memo) throws IOException {
		R<?> jsonResult = new R();
		if( StringUtils.isBlank(appId) || StringUtils.isBlank(configKeys) ) {
			jsonResult.setSuccess(Boolean.FALSE.booleanValue());
			jsonResult.setMsg("提交非法参数，无法批量添加！");
			return jsonResult;
		}
		String[] lines = configKeys.split("\n");
		boolean isProFormat = Boolean.TRUE.booleanValue();
		for(String line:lines) {
			if( StringUtils.isBlank(line) || line.charAt(0)=='#' ) continue;
			if( StringUtils.isNotBlank(line) && !line.contains("=") ) {
				isProFormat = Boolean.FALSE.booleanValue();
				break;
			}
		}
		
		Properties properties = new Properties();
		if( !isProFormat ) {
			properties = YamlPropUtil.yml2Properties(configKeys);
		}else {
			for(String line:lines) {
				log.info("添加属性：" + line);
				if( StringUtils.isBlank(line) || line.charAt(0)=='#' ) continue;
				String key = line.substring(0,line.indexOf("="));
				String value = line.substring(line.indexOf("=") + 1);
				log.info("添加属性：" + line);
				properties.setProperty(key, value);
			}
		}
		SysUser loginUser = (SysUser)request.getSession().getAttribute("useInfo");
		int effectCount = appConfigService.uploadProperties(loginUser,properties, overProp!=null && overProp.equals("on")?true:false, appId);
		jsonResult.setSuccess(Boolean.TRUE.booleanValue());
		jsonResult.setMsg("上传配置成功,添加更新[" + effectCount + "]条记录！");
		return jsonResult;
	}
	
	/**
	 * 新增应用配置项
	 * 
	 * @param appConfig 应用配置项
	 * @return R
	 */
	@RequestMapping(value = "/getLatestChangeLogs", produces = "application/json")
	public @ResponseBody R getLatestChangeLogs(HttpServletRequest request,String envType,String appId,String startDateTime,String endDateTime,String exportFormart,String includeAll) {
		R result = new R();
		if( StringUtils.isBlank(appId)) {
			result.setCode(IConstants.FAIL);
			result.setMsg("参数错误！");
			result.setSuccess(true);
			return result;
		}
		//获取数据
		QueryWrapper<AppConfig> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("app_id", appId);
		if( !"on".equals(includeAll) ) {
			SysUser loginUser = (SysUser)request.getSession().getAttribute("useInfo");
			queryWrapper.eq("user_id", String.valueOf(loginUser.getId()));
		}
		if( StringUtils.isNotBlank(startDateTime)) {
			queryWrapper.and(wrapper  -> wrapper.ge("create_time", startDateTime).or().ge("update_time", startDateTime));
		}
		if( StringUtils.isNotBlank(endDateTime)) {
			queryWrapper.and(wrapper  -> wrapper.ge("create_time", startDateTime).or().ge("update_time", startDateTime));
		}
		queryWrapper.orderByDesc("config_key");
		List<AppConfig> appConfigs = this.appConfigService.list(queryWrapper);
		if( appConfigs!=null && appConfigs.size()>0 ) {
			if( "yml".equals(exportFormart) ) {
				Properties props = new Properties();
				for(AppConfig appConfig:appConfigs) {
					props.put(appConfig.getConfigKey(), appConfig.getConfigValue());
				}
				String text = YamlPropUtil.properties2Yaml(props);
				result.setData(text);
			}else {
				StringBuffer text = new StringBuffer();
				for(AppConfig appConfig:appConfigs) {
					text.append(appConfig.getConfigKey()).append("=").append(appConfig.getConfigValue()).append("\r\n");
				}
				result.setData(text.toString());
			}
		}
		result.setCode(IConstants.SUCCESS);
		result.setMsg("获取成功！");
		result.setSuccess(true);
		return result;
	}
	
}
